//给定一个非空整数数组，除了某个元素只出现一次以外，其余每个元素均出现两次。找出那个只出现了一次的元素。 
//
// 说明： 
//
// 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗？ 
//
// 示例 1: 
//
// 输入: [2,2,1]
//输出: 1
// 
//
// 示例 2: 
//
// 输入: [4,1,2,1,2]
//输出: 4 
// Related Topics 位运算 数组 👍 2421 👎 0


import java.util.HashSet;
import java.util.Set;

//leetcode submit region begin(Prohibit modification and deletion)
class Solution0136 {
    /**
     * [136]只出现一次的数字 : 位运算之异或运算(两个自身异或为0,0和数字x异或还是x)
     * <p>
     * 空间复杂度: O(1)
     * <br>
     * 时间复杂度: O(n)
     * <p>
     * 注意审题:
     * 非空整数数组;
     * 某个元素只出现一次;
     * 其余每个元素均出现两次
     */
    public int singleNumber(int[] nums) {
        int singleNumber = 0;
        for (int num : nums) {
            singleNumber ^= num;
        }
        return singleNumber;
    }
}
//leetcode submit region end(Prohibit modification and deletion)


class Test0136 {
    public static void main(String[] args) {
        int[] nums = {2, 2, 1};
        System.out.println(singleNumber(nums));
    }


    /**
     * 用了两个哈希表, 空间换时间
     * <p>
     * 空间复杂度: O(2n) = O(n)
     * <br>
     * 时间复杂度: O(n)
     */
    public static int first(int[] nums) {
        Set<Integer> set = new HashSet<>(nums.length);
        Set<Integer> result = new HashSet<>(nums.length);
        for (int num : nums) {
            if (set.add(num)) {
                result.add(num);
            } else {
                result.remove(num);
            }
        }
        return result.iterator().next();
    }

    /**
     * 位运算: 异或运算
     * <p>
     * 空间复杂度: O(1)
     * <br>
     * 时间复杂度: O(n)
     * <p>
     * 注意审题:
     * 非空整数数组;
     * 某个元素只出现一次;
     * 其余每个元素均出现两次
     */
    public static int singleNumber(int[] nums) {
        int singleNumber = 0;
        for (int num : nums) {
            singleNumber ^= num;
        }
        return singleNumber;
    }
}